<?php
/**
 * DataCenter接口访问基类
 * @author JohnnyDen <413819942@qq.com>
 * @package Lib\WGDC\Core
 * @copyright 2017年12月8日
 */
namespace NMClient\Core;

class Http {
    
    //接口地址
    static private $url             = DATA_CENTER_URL;
    //应用程序帐号
    static private $clientID        = DATA_CENTER_CLIENT_ID;
    //应用程序密钥 
    static private $clientSecret    = DATA_CENTER_CLIENT_SECRET;
    //通信加密级别
    static private $crypt_level     = DATA_CENTER_CRYPT_LEVEL;
    
    //签名方式
    static private $signType        = 'md5';
    
    //请求信息，用于调试
    static private $_requestInfo    = array();
    
    /**
     * 获取CLientID
     * @return number
     */
    static public function getClientID() {
        return self::$clientID;
    }
    
    /**
     * 测试连访问是否成功
     * @return array
     */
    static public function test() {
        return self::call('Test', 'index', array('test' => 'this is post params.'), null, 0);
    }
    
    /**
     * 请求信息，用于调试
     * @return array
     */
    static public function requestInfo() {
        $total  = 0;
        if (self::$_requestInfo['TIME']) {
            foreach (self::$_requestInfo['TIME'] as $key => $value) {
                $total  += $value;
                self::$_requestInfo['TIME'][$key]   = abs( round($value, 6) );
            }
            self::$_requestInfo['TIME']['_TOTAL_']  = abs( round($total, 6) );
        }
        return self::$_requestInfo;
    }
    
    /**
     * 编码提交的数据
     * @param array $data
     * @return string json格式
     */
    static private function _encode($data, $encrypt) {
        if (!$encrypt) {
            return $data;
        }
        $data = json_encode($data);
        $des_key    = self::$clientID.'-'.rand(10000000, 99999999).'-'.time();
        $des_key    = $des_key.'-'.md5($des_key);
        
        self::$_requestInfo['crypt']['des_key']  = $des_key;
        $data       = \NMClient\Core\Crypt\Des::encrypt($data, $des_key);
        $des_key    = \NMClient\Core\Crypt\Rsa::pubEncrypt($des_key);
        
        self::$_requestInfo['crypt']['des_data'] = $data;
        self::$_requestInfo['crypt']['rsa_key']  = $des_key;
        
        return array(
            'data'  => $data,
            'key'   => $des_key,
        );
    }
    
    /**
     * 解码接收的数据
     * @param string $response json串
     * @return array
     */
    static private function _decode($response, $encrypt) {
        $response   = json_decode($response, true);
        if ($response['status'] && !$response['key']) {
            return $response;
        }
        $des_key    = \NMClient\Core\Crypt\Rsa::pubDecrypt($response['key']);
        return json_decode( \NMClient\Core\Crypt\Des::decrypt($response['data'], $des_key), true );
    }
    
    /**
     * 接口调用
     * 组装请求，接收结果并解码（加签-编码-请求-接收-解码-返回）
     * @param string $controller 请求控制器名称
     * @param string $action 请求方法名
     * @param array $post 提交的数据
     * @param string $access_token 通信身份确认标识
     * @param bool $encrypt 是否加密通信
     * @return array
     * <code>
     * array(
     *         'status'     => 'ok',
     *         'info'       => '',
     *         'data'       => array()
     * )
     * </pre>
     */
    static public function call($controller, $action, $post, $access_token, $crypt_level, $is_upload = false) {
        self::$_requestInfo['TIME']['server_time']  = microtime(true);
        $timestamp  = self::_timestamp();
        self::$_requestInfo['TIME']['server_time']  -= microtime(true);
        
        $func       = self::$signType;
        self::$_requestInfo['TIME']['sign']  = microtime(true);
        $sign       = $func(self::$clientSecret.'-'.self::$clientID.'-'.$timestamp.'-'.self::$crypt_level);
        self::$_requestInfo['TIME']['sign']  -= microtime(true);
        $access_token_str   = $access_token ? "&access_token={$access_token}" : '';
        $url        = self::$url."?s=/{$controller}/{$action}&timestamp={$timestamp}{$access_token_str}&crypt_level=".self::$crypt_level."&sign={$sign}&client_id=".self::$clientID;
        self::$_requestInfo['url']      = $url;
        self::$_requestInfo['post']     = $post;
        self::$_requestInfo['sign']     = $sign;
        self::$_requestInfo['signType'] = $func;
        self::$_requestInfo['timestamp']= $timestamp;
        
        if (!$post) {
            $result = self::_curl($url);
        } else {
            self::$_requestInfo['TIME']['encode']    = microtime(true);
            $encode = self::_encode($post, $crypt_level > self::$crypt_level);
            self::$_requestInfo['TIME']['encode']    -= microtime(true);
            self::$_requestInfo['TIME']['curl']      = microtime(true);
            $result = self::_curl($url, 'post', $encode, $is_upload);
            self::$_requestInfo['TIME']['curl']      -= microtime(true);
        }
        
        self::$_requestInfo['response'] = $result;
        self::$_requestInfo['TIME']['decode']    = microtime(true);
        $result     = self::_decode($result, $crypt_level > self::$crypt_level);
        self::$_requestInfo['TIME']['decode']    -= microtime(true);
        self::$_requestInfo['result'] = $result;
        
        return $result;
    }
    
    /**
     * CURL请求获取数据
     * @param string $url 请求地址
     * @param string $method 请求类型：get | post
     * @param array $data post数据集
     * @param bool $is_upload 是否是上传图片
     * @return string 请求结果
     */
    static private function _curl($url, $method = 'get', $data = array(), $is_upload = false) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        if (!$is_upload) {
            $data   = json_encode($data);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('content-type:application/json'));
        }
        
        if ($method == 'post') {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        
        $result = curl_exec($ch);
        curl_close($ch);
        
        return $result;
    }
    
    /**
     * 日志写入接口
     * @param string $log 日志信息
     * @param string $destination  写入目标
     * @return void
     */
    static public function LogW($log, $destination='') {
        $_log_file_size     = 2097152;
    
        if (empty($destination)) {
            $destination    = date('y_m_d').'.log';
        }
        $destination        = './runtime/log_nmclient/'.$destination;
        //自动创建日志目录
        $log_dir = dirname($destination);
        if (!is_dir($log_dir)) {
            mkdir($log_dir, 0755, true);
        }
        //检测日志文件大小，超过配置大小则备份日志文件重新生成
        if (is_file($destination) && $_log_file_size <= filesize($destination)) {
            rename($destination,dirname($destination).'/'.time().'-'.basename($destination));
        }
        error_log( $log."\r\n", 3,$destination);
    }
    
    /**
     * 获取当前时间
     * @return number
     */
    static private function _timestamp() {
        return time();
//         static $timestamp, $server_time;
//         if (!isset($timestamp)) {
//             $server_time    = time();
//             $timestamp  = (int)self::_curl(self::$url.'?c=General/Public&a=serverTime');
//         } else {
//             $time       = time();
//             $timestamp  += $time - $server_time;
//             $server_time= $time;
//         }
        
//         return $timestamp;
    }
}